package utils

import (
	"HeadLineNews/proto_models/app/account_model"
	"HeadLineNews/proto_models/common"
	models "HeadLineNews/proto_models/manage/admin_model"
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"google.golang.org/protobuf/proto"
	"io/ioutil"
	"log"
	"net/http"
)

var (
	ErrMarshal      = "marshal message failed. error: %v"
	ErrBuildRequest = "build new request failed. error: %v"
	ErrGetResponse  = "get response failed. error: %v"
	ErrReadResponse = "read response failed. error: %v"
)

const secretKet = "secretKey"

// EncodeString 密码（加密）
func EncodeString(str string) string {
	m := md5.New()
	m.Write([]byte(secretKet))
	m.Write([]byte(str))
	return hex.EncodeToString(m.Sum(nil))
}

// GetProtobuf protobuf get 请求
func GetProtobuf(url string, headers map[string]string) (content []byte, err error) {
	// 构建新请求
	var request *http.Request
	if request, err = http.NewRequest("GET", url, nil); err != nil {
		err = fmt.Errorf(ErrBuildRequest, err)
		return
	}
	if headers != nil {
		for k, v := range headers {
			request.Header.Set(k, v)
		}
	}
	// 获取响应
	var response *http.Response
	if response, err = http.DefaultClient.Do(request); err != nil {
		err = fmt.Errorf(ErrGetResponse, err)
		return
	}
	// 从 response 中解析数据
	if content, err = ioutil.ReadAll(response.Body); err != nil {
		err = fmt.Errorf(ErrReadResponse, err)
		return
	}
	return
}

// PostProtobuf 封装 protobuf 的 post 请求
func PostProtobuf(url string, p proto.Message, headers map[string]string) (content []byte, err error) {
	// 序列化数据
	var bytesData []byte
	if bytesData, err = proto.Marshal(p); err != nil {
		err = fmt.Errorf(ErrMarshal, err)
		return
	}
	// 构建新请求
	var request *http.Request
	if request, err = http.NewRequest("POST", url, bytes.NewReader(bytesData)); err != nil {
		err = fmt.Errorf(ErrBuildRequest, err)
		return
	}
	if headers != nil {
		for k, v := range headers {
			request.Header.Set(k, v)
		}
	}
	// 获取响应
	var response *http.Response
	if response, err = http.DefaultClient.Do(request); err != nil {
		err = fmt.Errorf(ErrGetResponse, err)
		return
	}
	// 从 response 中解析数据
	if content, err = ioutil.ReadAll(response.Body); err != nil {
		err = fmt.Errorf(ErrReadResponse, err)
		return
	}
	return
}

// ParseProtobufRes 解析第一层 response
func ParseProtobufRes(content []byte, body proto.Message) (msg proto.Message, err error) {
	// 解析第一层 response
	res := &common.Response{}
	if err = proto.Unmarshal(content, res); err != nil {
		return
	}
	if res.Message != "success" {
		err = errors.New("异常响应 ↓↓↓")
		msg = res
		return
	}
	// body 不为空则返回 body
	if body != nil {
		if err = res.Data.UnmarshalTo(body); err != nil {
			return
		}
		msg = body
		return
	} else {
		msg = res
	}
	return
}

// AdminLogin 返回 login 的登录 token
func AdminLogin(adminName, adminPwd string) string {
	if adminName == "" || adminPwd == "" {
		adminName = "Leon"
		adminPwd = "123"
	}
	url := `http://127.0.0.1:8080/api/admin/login/`
	p := &models.RequestAdminLogin{
		AdminName: adminName,
		AdminPwd:  EncodeString(adminPwd),
	}
	content, err := PostProtobuf(url, p, nil)
	if err != nil {
		log.Fatalf("admin login response failed. error: %v", err)
	}

	var body = &models.ResponseAdminLoginRegister{}
	var message proto.Message
	if message, err = ParseProtobufRes(content, body); err != nil {
		log.Fatalf("parse admin login response failed. error: %v", err)
	}
	if msg, ok := message.(*common.Response); ok {
		log.Println(msg)
	}
	if msg, ok := message.(*models.ResponseAdminLoginRegister); ok {
		return msg.Authorization
	}
	return ""
}

// UserLogin 用户登录
func UserLogin(userName, password string) string {
	if userName == "" || password == "" {
		userName = "Leon"
		password = "123"
	}
	url := `http://127.0.0.1:8080/api/user/login/`
	p := &account_model.RequestUserLogin{
		UserName: userName,
		UserPwd:  EncodeString(password),
	}
	content, err := PostProtobuf(url, p, nil)
	if err != nil {
		log.Fatalf("user login response failed. error: %v", err)
	}

	var body = &account_model.ResponseUserLoginRegister{}
	var message proto.Message
	if message, err = ParseProtobufRes(content, body); err != nil {
		log.Fatalf("parse user login response failed. error: %v", err)
	}
	if msg, ok := message.(*common.Response); ok {
		log.Println(msg)
	}
	if msg, ok := message.(*account_model.ResponseUserLoginRegister); ok {
		return msg.Authorization
	}
	return ""

}

// NewAdminAuthHeaders token 信息头
func NewAdminAuthHeaders(adminName, adminPwd string) map[string]string {
	return map[string]string{"authorization": AdminLogin(adminName, adminPwd)}
}

// NewUserAuthHeaders token 信息头
func NewUserAuthHeaders(userName, password string) map[string]string {
	return map[string]string{"authorization": UserLogin(userName, password)}
}